package com.leyou.item.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.common.pojo.PageResult;
import com.leyou.common.utils.BeanHelper;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class GoodsService extends ServiceImpl<SkuMapper, Sku> {

    @Autowired(required = false)
    private SpuMapper spuMapper;

    @Autowired(required = false)
    private SpuDetailMapper detailMapper;

    @Autowired(required = false)
    private SkuMapper skuMapper;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private BrandService brandService;

    @Autowired(required = false)
    private SpuDetailMapper spuDetailMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;


    /**
     * 商品的分页查询
     * @param key  搜索关键字
     * @param saleable 是否上下架
     * @param page 第几页
     * @param rows 每页大小
     * @return
     */
    public PageResult<SpuDTO> goodsPageQuery(String key, Boolean saleable, Integer page, Integer rows) {

        //提供分页信息
        IPage<Spu> ipage = new Page<>(page, rows);
        //提供封装查询条件对象
        QueryWrapper<Spu> wrapper = Wrappers.query();
        //判断是否有查询关键字
        if (StringUtils.isNotEmpty(key)){
            wrapper.like("name", key);
        }
        //判断是否上下架查询条件
        if (saleable!=null){
            wrapper.eq("saleable", saleable);
        }
        //执行分页查询
        ipage = spuMapper.selectPage(ipage, wrapper);
        //提取分页结果spu列表
        List<Spu> spus = ipage.getRecords();
        //判断是否为空
        if (CollectionUtils.isEmpty(spus)){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        //将List<Spu>转成List<SpuDTO>
        List<SpuDTO> spuDTOS = BeanHelper.copyWithCollection(spus, SpuDTO.class);
        //给SpuDTO集合中每个SpuDTO对象的分类和品牌名称赋值
        handlerBrandNameAndCategoryName(spuDTOS);
        //得到自定义的分页对象
        PageResult<SpuDTO> pageResult = new PageResult<>(ipage.getTotal(),ipage.getPages(),spuDTOS);

        return pageResult;
    }


    /*给SpuDTO集合中每个SpuDTO对象的分类和品牌名称赋值*/
    private void handlerBrandNameAndCategoryName(List<SpuDTO> spuDTOS) {
        spuDTOS.forEach(spuDTO -> {
            //根据品牌id获取品牌对象
            Brand brand = brandService.findBrandById(spuDTO.getBrandId());
            //给品牌名称赋值
            spuDTO.setBrandName(brand.getName());
            //获取分类名称的拼接字符串
            String categoryNames = categoryService.findCategorysByIds(spuDTO.getCategoryIds())
                    //将集合转成流
                    .stream()
                    //收集Category中的name值
                    .map(Category::getName)
                    //把多个分类的名称以"|"拼接到一起
                    .collect(Collectors.joining("|"));

            //给分类的名称赋值
            spuDTO.setCategoryName(categoryNames);
        });
    }


    /**
     * 商品保存
     */
    public void saveGoods(SpuDTO spuDto) {
        try {
            //获取spu对象
            Spu spu = BeanHelper.copyProperties(spuDto, Spu.class);
            //设置为下架状态
            spu.setSaleable(false);
            //保存spu对象
            spuMapper.insert(spu);

            //获取spuDetail对象
            SpuDetail spuDetail = spuDto.getSpuDetail();
            //设置给主键赋值
            spuDetail.setSpuId(spu.getId());
            //保存spuDetail对象
            spuDetailMapper.insert(spuDetail);

            //获取sku集合
            List<Sku> skuList = spuDto.getSkus();
            //遍历sku集合 设置外键的值
            skuList.forEach(sku -> {
                sku.setSpuId(spu.getId());
            });

            //保存sku集合
            saveBatch(skuList);
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }


    /**
     * 商品上下架
     */
    public void updateSaleable(Long id, Boolean saleable) {
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        int count = spuMapper.updateById(spu);
        if (count==0){
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }

        //商品上下架的同时，要处理索引库和静态化页面的同步问题,根据上下架来指定不同的routingKey
        String routingkey = saleable ? MQConstants.RoutingKey.ITEM_UP_KEY  : MQConstants.RoutingKey.ITEM_DOWN_KEY;

        //把需要同步的数据放入MQ中
        //参数一：exchange交换机, 参数二：routingKey, 参数三：要发送的数据，可以是任何格式
        amqpTemplate.convertAndSend(MQConstants.Exchange.ITEM_EXCHANGE_NAME,routingkey,id);
    }


    /**
     * 根据SpuId查询SpuDetail对象
     */
    public SpuDetail findSpuDetailById(Long id) {

        SpuDetail spuDetail = spuDetailMapper.selectById(id);
        if (spuDetail==null){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return spuDetail;
    }


    /**
     * 根据SpuId查询Sku集合
     */
    public List<Sku> findSkusBySpuId(Long id) {
        //创建查询对象
        Sku sku = new Sku();
        sku.setSpuId(id);
        //创建查询条件对象
        QueryWrapper<Sku> wrapper = Wrappers.query(sku);
        //查询
        List<Sku> skuList = skuMapper.selectList(wrapper);
        //空判断
        if (CollectionUtils.isEmpty(skuList)){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return skuList;
    }


    /**
     * 根据spuId查询SpuDto对象
     */
    public SpuDTO findSpuDtoById(Long id) {

        Spu spu = spuMapper.selectById(id);
        if (spu==null){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        //将Spu转换成SpuDto对象
        SpuDTO spuDTO = BeanHelper.copyProperties(spu,SpuDTO.class);
        //根据id查询SpuDetail
        SpuDetail spuDetail = findSpuDetailById(id);
        //把spuDetail赋值给spuDto
        spuDTO.setSpuDetail(spuDetail);
        //根据spuId查询sku集合
        List<Sku> skus = findSkusBySpuId(id);
        spuDTO.setSkus(skus);
        return spuDTO;
    }


    /**
     * 根据id批量查询sku
     * @param ids skuId的集合
     * @return sku的集合
     */
    public List<Sku> findSkusByIds(List<Long> ids) {

        List<Sku> skus = skuMapper.selectBatchIds(ids);
        if (CollectionUtils.isEmpty(skus)){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return skus;
    }


    /**
     * 减库存
     * @param paramMap 商品id及数量的map
     */
    public void minusStock(Map<Long, Integer> paramMap) {
        paramMap.entrySet().forEach(entry->{
            //获取skuId
            Long skuId = entry.getKey();
            //要减的数量
            Integer num = entry.getValue();
            //减库存
            skuMapper.minusStock(skuId,num);

            //==========错误写法(导致超卖问题)==========
//            //封装减库存的条件
//            Sku record = new Sku();
//            record.setId(skuId);
//            Sku sku = skuMapper.selectById(skuId);
//            record.setStock(sku.getStock()-num);
//            //减库存
//            skuMapper.updateById(record);
        });
    }

    /**
     * 归还失效订单的库存
     * @param skuId
     * @param num
     */
    public void returnSku(Long skuId, Integer num) {
        skuMapper.returnSku(skuId,num);
    }
}